home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1146 / 1146.xpi / chrome / screengrab.jar / content / external / log4js.js next >
Text File  |  2009-03-09  |  31KB  |  1,198 lines

  1. /*
  2.  * Licensed under the Apache License, Version 2.0 (the "License");
  3.  * you may not use this file except in compliance with the License.
  4.  * You may obtain a copy of the License at
  5.  *
  6.  *      http://www.apache.org/licenses/LICENSE-2.0
  7.  *
  8.  * Unless required by applicable law or agreed to in writing, software
  9.  * distributed under the License is distributed on an "AS IS" BASIS,
  10.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11.  * See the License for the specific language governing permissions and
  12.  * limitations under the License.
  13.  */
  14.  
  15. /**
  16.  * @fileoverview log4js is a library to log in JavaScript in simmilar manner 
  17.  * than in log4j for Java. The API should be nearly the same.
  18.  * <h3>Example:</h3>
  19.  * <pre>
  20.  *  //logging see log4js
  21.  *  var log = new Log4js.getLogger("some-category-name"); 
  22.  *  log.setLevel(Log4js.Level.TRACE); //set the Level
  23.  *  log.addAppender(new ConsoleAppender(log, false)); // console that launches in new window
  24.  
  25.  *  // if multiple appenders are set all will log
  26.  *  log.addAppender(new ConsoleAppender(log, true)); // console that is inline in the page
  27.  *  log.addAppender(new FileAppender("C:\\somefile.log")); // file appender logs to C:\\somefile.log
  28.  *  ...
  29.  *  //call the log
  30.  *  log.trace("trace me" );
  31.  * </pre>
  32.  *
  33.  * @version 0.2 variant for Firefox extensions
  34.  * Lots of bits culled, and prototype stuff removed - trying to be a good citizen in extension land
  35.  * @author Andrew Mutton - http://www.screengrab.org
  36.  * @author Stephan Strittmatter - http://jroller.com/page/stritti
  37.  * @author Seth Chisamore - http://www.chisamore.com
  38.  */
  39. var Log4js = {
  40.     /**  
  41.      * map of loggers
  42.      * @static
  43.      * @final
  44.      * @private  
  45.      */
  46.     loggerMap: new Map(),
  47.     
  48.     /** 
  49.      * current version of log4js 
  50.      * @static
  51.      * @final
  52.      */
  53.       version: "0.2",
  54.     
  55.     setSimpleDate : function(simpledate) {
  56.         Log4js.simpledate = simpledate;
  57.     },
  58.     
  59.     /**
  60.      * Get a logger instance. Instance is cached on categoryName level.
  61.      * @param  {String} categoryName name of category to log to.
  62.      * @return {Logger} instance of logger for the category
  63.      * @static
  64.      */
  65.     getLogger: function(categoryName) {
  66.         if (!Log4js.loggerMap.contains(categoryName))
  67.         {
  68.                Log4js.loggerMap.put(categoryName, new Log4js.Logger(categoryName));
  69.         }
  70.         return Log4js.loggerMap.get(categoryName); 
  71.     },
  72.       /**
  73.        * @param element
  74.        * @param name
  75.        * @param observer
  76.        * @private
  77.        */
  78.       attachEvent: function (element, name, observer) {
  79.         if (element.addEventListener) {
  80.             element.addEventListener(name, observer, false);
  81.         } else if (element.attachEvent) {
  82.             element.attachEvent('on' + name, observer);
  83.         }
  84.     }
  85. };
  86.  
  87.  
  88.  
  89.  
  90. /**
  91.  * Log4js.Level Enumeration. Do not use directly. Use static objects instead.
  92.  * @constructor
  93.  * @param {Number} level
  94.  * @param {String} levelString
  95.  */
  96. Log4js.Level = function(level, levelStr) {
  97.     this.level = level;
  98.     this.levelStr = levelStr;
  99. };
  100.  
  101. Log4js.Level.prototype =  {
  102.     /** 
  103.      * converts given String to corresponding Level
  104.      * @param {String} sArg String value of Level
  105.      * @param {Log4js.Level} defaultLevel default Level, if no String representation
  106.      * @return Level object
  107.      * @type Log4js.Level
  108.      */
  109.     toLevel: function(sArg, defaultLevel) {                  
  110.                 
  111.         if(sArg === null) {
  112.             return defaultLevel;
  113.         }
  114.         
  115.         if(typeof sArg == "string") { 
  116.             var s = sArg.toUpperCase();
  117.             if(s == "ALL") {return Log4js.Level.ALL;}
  118.             if(s == "DEBUG") {return Log4js.Level.DEBUG;}
  119.             if(s == "INFO") {return Log4js.Level.INFO;}
  120.             if(s == "WARN") {return Log4js.Level.WARN;}
  121.             if(s == "ERROR") {return Log4js.Level.ERROR;}
  122.             if(s == "FATAL") {return Log4js.Level.FATAL;}
  123.             if(s == "OFF") {return Log4js.Level.OFF;}
  124.             if(s == "TRACE") {return Log4js.Level.TRACE;}
  125.             return defaultLevel;
  126.         } else if(typeof sArg == "number") {
  127.             switch(sArg) {
  128.                 case ALL_INT: return Log4js.Level.ALL;
  129.                 case DEBUG_INT: return Log4js.Level.DEBUG;
  130.                 case INFO_INT: return Log4js.Level.INFO;
  131.                 case WARN_INT: return Log4js.Level.WARN;
  132.                 case ERROR_INT: return Log4js.Level.ERROR;
  133.                 case FATAL_INT: return Log4js.Level.FATAL;
  134.                 case OFF_INT: return Log4js.Level.OFF;
  135.                 case TRACE_INT: return Log4js.Level.TRACE;
  136.                 default: return defaultLevel;
  137.             }
  138.         } else {
  139.             return defaultLevel;    
  140.         }
  141.     },    
  142.     /** 
  143.      * @return  converted Level to String
  144.      * @type String
  145.      */        
  146.     toString: function() {
  147.         return this.levelStr;    
  148.     },
  149.     /** 
  150.      * @return internal Number value of Level
  151.      * @type Number
  152.      */            
  153.     valueOf: function() {
  154.         return this.level;
  155.     }
  156. };
  157.  
  158. // Static variables
  159. /** 
  160.  * @private
  161.  */
  162. Log4js.Level.OFF_INT = Number.MAX_VALUE;
  163. /** 
  164.  * @private
  165.  */
  166. Log4js.Level.FATAL_INT = 50000;
  167. /** 
  168.  * @private
  169.  */
  170. Log4js.Level.ERROR_INT = 40000;
  171. /** 
  172.  * @private
  173.  */
  174. Log4js.Level.WARN_INT = 30000;
  175. /** 
  176.  * @private
  177.  */
  178. Log4js.Level.INFO_INT = 20000;
  179. /** 
  180.  * @private
  181.  */
  182. Log4js.Level.DEBUG_INT = 10000;
  183. /** 
  184.  * @private
  185.  */
  186. Log4js.Level.TRACE_INT = 5000;
  187. /** 
  188.  * @private
  189.  */
  190. Log4js.Level.ALL_INT = Number.MIN_VALUE;
  191.  
  192. /** 
  193.  * Logging Level OFF - all disabled
  194.  * @type Log4js.Level
  195.  * @static
  196.  */
  197. Log4js.Level.OFF = new Log4js.Level(Log4js.Level.OFF_INT, "OFF");
  198. /** 
  199.  * Logging Level Fatal
  200.  * @type Log4js.Level
  201.  * @static
  202.  */
  203. Log4js.Level.FATAL = new Log4js.Level(Log4js.Level.FATAL_INT, "FATAL");
  204. /** 
  205.  * Logging Level Error
  206.  * @type Log4js.Level
  207.  * @static
  208.  */
  209. Log4js.Level.ERROR = new Log4js.Level(Log4js.Level.ERROR_INT, "ERROR"); 
  210. /** 
  211.  * Logging Level Warn
  212.  * @type Log4js.Level
  213.  * @static
  214.  */
  215. Log4js.Level.WARN = new Log4js.Level(Log4js.Level.WARN_INT, "WARN"); 
  216. /** 
  217.  * Logging Level Info
  218.  * @type Log4js.Level
  219.  * @static
  220.  */
  221. Log4js.Level.INFO = new Log4js.Level(Log4js.Level.INFO_INT, "INFO");     
  222. /** 
  223.  * Logging Level Debug
  224.  * @type Log4js.Level
  225.  * @static
  226.  */
  227. Log4js.Level.DEBUG = new Log4js.Level(Log4js.Level.DEBUG_INT, "DEBUG");  
  228. /** 
  229.  * Logging Level Trace
  230.  * @type Log4js.Level
  231.  * @static
  232.  */
  233. Log4js.Level.TRACE = new Log4js.Level(Log4js.Level.TRACE_INT, "TRACE");  
  234. /** 
  235.  * Logging Level All - All traces are enabled
  236.  * @type Log4js.Level
  237.  * @static
  238.  */
  239. Log4js.Level.ALL = new Log4js.Level(Log4js.Level.ALL_INT, "ALL"); 
  240.  
  241. /**
  242.  * Log4js CustomEvent
  243.  * @constructor
  244.  * @author Corey Johnson - original code in Lumberjack (http://gleepglop.com/javascripts/logger/)
  245.  * @author Seth Chisamore - adapted for Log4js
  246.  * @private
  247.  */
  248. Log4js.CustomEvent = function() {
  249.     this.listeners = [];
  250. };
  251.  
  252. Log4js.CustomEvent.prototype = {
  253.  
  254.      /**
  255.       * @param method method to be added
  256.       */ 
  257.     addListener : function(method) {
  258.         this.listeners.push(method);
  259.     },
  260.  
  261.      /**
  262.       * @param method method to be removed
  263.       */ 
  264.     removeListener : function(method) {
  265.         var foundIndexes = this._findListenerIndexes(method);
  266.  
  267.         for(var i = 0; i < foundIndexes.length; i++) {
  268.             this.listeners.splice(foundIndexes[i], 1);
  269.         }
  270.     },
  271.  
  272.      /**
  273.       * @param handler
  274.       */ 
  275.     dispatch : function(handler) {
  276.         for(var i = 0; i < this.listeners.length; i++) {
  277.             try {
  278.                 this.listeners[i].doAppend(handler);
  279.             }
  280.             catch (e) {
  281.                 alert("Could not run the listener " + this.listeners[i] + ". \n" + e);
  282.             }
  283.         }
  284.     },
  285.  
  286.     /**
  287.      * @private
  288.      * @param method
  289.      */
  290.     _findListenerIndexes : function(method) {
  291.         var indexes = [];
  292.         for(var i = 0; i < this.listeners.length; i++) {            
  293.             if (this.listeners[i] == method) {
  294.                 indexes.push(i);
  295.             }
  296.         }
  297.  
  298.         return indexes;
  299.     }
  300. };
  301.  
  302. /**
  303.  * Models a logging event.
  304.  * @constructor
  305.  * @param {String} categoryName name of category
  306.  * @param {Log4js.Level} level level of message
  307.  * @param {String} message message to log
  308.  * @param {Log4js.Logger} logger the associated logger
  309.  * @author Seth Chisamore
  310.  */
  311. Log4js.LoggingEvent = function(categoryName, level, message, logger, stackInfo, fullStack) {
  312.     /**
  313.      * @type Date
  314.      * @private
  315.      */
  316.     this.startTime = new Date();
  317.     /**
  318.      * @type String
  319.      * @private
  320.      */
  321.     this.categoryName = categoryName || ".";
  322.     /**
  323.      * @type String
  324.      * @private
  325.      */
  326.     this.message = message || "";
  327.     /**
  328.      * @type Log4js.Level
  329.      * @private
  330.      */
  331.     this.level = level || Log4js.Level.TRACE;
  332.     /**
  333.      * @type Log4js.Logger
  334.      * @private
  335.      */
  336.     this.logger = logger;
  337.     /**
  338.      * @type String
  339.      * @private
  340.      */
  341.     this.stackInfo = stackInfo;
  342.     this.fullStack = fullStack;
  343. };
  344.  
  345. Log4js.LoggingEvent.prototype = {
  346.  
  347.     /**
  348.      * Returns the layouted message line
  349.      * @return layouted Message
  350.      * @type String
  351.      * @deprecated use Layout instead.
  352.      */
  353.     getRenderedMessage: function() {
  354.         return this.categoryName + "~" + this.startTime.toLocaleString() + " [" + this.level.toString() + "] " + this.message;
  355.     },
  356.     
  357.     getStackFileName : function() {
  358.         if (this.stackInfo != null) {
  359.             var split = this.stackInfo.split(" :: ");
  360.             var fileName = split[1];
  361.             if (fileName.lastIndexOf("/") != -1) {
  362.                 var pathSplit = fileName.split("/");
  363.                 fileName = pathSplit[pathSplit.length - 1];
  364.             }
  365.             return fileName
  366.         }
  367.         return null;
  368.     },
  369.     
  370.     getStackLineNum : function() {
  371.         if (this.stackInfo != null) {
  372.             var split = this.stackInfo.split(" :: ");
  373.             var lineNum = split[3].split(" ")[1];
  374.             return lineNum;
  375.         }
  376.         return null;
  377.     }
  378. };
  379.  
  380. /**
  381.  * Logger to log messages to the defined appender.</p>
  382.  * Default appender is Appender, which is ignoring all messages. Please
  383.  * use setAppender() to set a specific appender (e.g. WindowAppender).
  384.  * use {@see Log4js#getLogger(String)} to get an instance.
  385.  * @constructor
  386.  * @param name name of category to log to
  387.  * @author Stephan Strittmatter
  388.  */
  389. Log4js.Logger = function(name) {
  390.     this.loggingEvents = [];
  391.     this.appenders = [];
  392.     /** category of logger */
  393.     this.category = name || "";
  394.     /** level to be logged */
  395.     this.level = Log4js.Level.FATAL;
  396.     
  397.     this.onlog = new Log4js.CustomEvent();
  398.     
  399.     /** appender to write in */
  400.     this.appenders.push(new Appender(this));
  401. };
  402.  
  403. Log4js.Logger.prototype = {
  404.  
  405.     /**
  406.      * add additional appender. DefaultAppender always is there.
  407.      * @param appender additional wanted appender
  408.      */
  409.     addAppender: function(appender) {
  410.         this.appenders.push(appender);
  411.     },
  412.  
  413.     /**
  414.      * Set the Loglevel default is LogLEvel.TRACE
  415.      * @param level wanted logging level
  416.      */
  417.     setLevel: function(level) {
  418.         this.level = level;
  419.     },
  420.     
  421.     getStack: function() {
  422.         if (!Components && !Components.stack) {
  423.             return "";
  424.         }
  425.         var asString = "";
  426.         var stack = Components.stack;
  427.         while (stack != null) {
  428.             var toStr = stack.toString();
  429.             if (toStr.indexOf("log4js.js") == -1 || toStr.indexOf("Log4js.js") == -1) {
  430.                 asString += toStr + "\n";
  431.             }
  432.             stack = stack.caller;
  433.         }
  434.         return asString;
  435.     },
  436.     
  437.     /** main log method logging to all available appenders */
  438.     log: function(message, logLevel) {
  439.         if (Components && Components.stack) {
  440.             var stack = Components.stack.caller;
  441.             while ((stack.toString().indexOf("log4js.js") != -1 || stack.toString().indexOf("Log4js.js") != -1) && stack.caller != null) {
  442.                 stack = stack.caller;
  443.             }
  444.             var fullStack = null;
  445.             if (logLevel == Log4js.Level.ERROR) {
  446.                 fullStack = this.getStack();
  447.             }
  448.             var loggingEvent = new Log4js.LoggingEvent(this.category, logLevel, message, this, stack.toString(), fullStack);
  449.         } else {
  450.             var loggingEvent = new Log4js.LoggingEvent(this.category, logLevel, message, this);
  451.         }
  452.         this.loggingEvents.push(loggingEvent);
  453.         this.onlog.dispatch(loggingEvent);
  454.     },
  455.     
  456.     /** checks if Level Trace is enabled */
  457.     isTraceEnabled: function() {
  458.         if (this.level.valueOf() <= Log4js.Level.TRACE.valueOf()) {
  459.             return true;
  460.         }
  461.         return false;
  462.     },
  463.     /** logging trace messages */
  464.     trace: function(message) {
  465.         if (this.isTraceEnabled()) {
  466.             this.log(message, Log4js.Level.TRACE);
  467.         }
  468.     },
  469.     /** checks if Level Debug is enabled */
  470.     isDebugEnabled: function() {
  471.         if (this.level.valueOf() <= Log4js.Level.DEBUG.valueOf()) {
  472.             return true;
  473.         }
  474.         return false;
  475.     },
  476.     /** logging debug messages */
  477.     debug: function(message) {
  478.         if (this.isDebugEnabled()) {
  479.             this.log(message, Log4js.Level.DEBUG);
  480.         }
  481.     },
  482.     /** checks if Level Info is enabled */
  483.     isInfoEnabled: function() {
  484.         if (this.level.valueOf() <= Log4js.Level.INFO.valueOf()) {
  485.             return true;
  486.         }
  487.         return false;
  488.     },
  489.     /** logging info messages */
  490.     info: function(message) {
  491.         if (this.isInfoEnabled()) {
  492.             this.log(message, Log4js.Level.INFO);
  493.         }
  494.     },
  495.     /** checks if Level Warn is enabled */
  496.     isWarnEnabled: function() {
  497.         if (this.level.valueOf() <= Log4js.Level.WARN.valueOf()) {
  498.             return true;
  499.         }
  500.         return false;
  501.     },
  502.  
  503.     /** logging warn messages */
  504.     warn: function(message) {
  505.         if (this.isWarnEnabled()) {
  506.             this.log(message, Log4js.Level.WARN);
  507.         }
  508.     },
  509.     /** checks if Level Error is enabled */
  510.     isErrorEnabled: function() {
  511.         if (this.level.valueOf() <= Log4js.Level.ERROR.valueOf()) {
  512.             return true;
  513.         }
  514.         return false;
  515.     },
  516.     /** logging error messages */
  517.     error: function(message) {
  518.         if (this.isErrorEnabled()) {
  519.             this.log(message, Log4js.Level.ERROR);
  520.         }
  521.     },
  522.     /** checks if Level Fatal is enabled */
  523.     isFatalEnabled: function() {
  524.         if (this.level.valueOf() <= Log4js.Level.FATAL.valueOf()) {
  525.             return true;
  526.         }
  527.         return false;
  528.     },
  529.     /** logging fatal messages */
  530.     fatal: function(message) {
  531.         if (this.isFatalEnabled()) {
  532.             this.log(message, Log4js.Level.FATAL);
  533.         }
  534.     },
  535.     
  536.     /** capture main window errors and log as fatal */
  537.     windowError: function(msg, url, line){
  538.         var message = "Error in (" + (url || window.location) + ") on line "+ line +" with message (" + msg + ")";
  539.         this.log(message, Log4js.Level.FATAL);    
  540.     }
  541. };
  542.  
  543. /**
  544.  * Interface for Appender.
  545.  * Use this appender as "interface" for other appenders. It is doing nothing.
  546.  *
  547.  * @constructor
  548.  * @param {Log4js.Logger} logger log4js instance this appender is attached to
  549.  * @author Stephan Strittmatter
  550.  */
  551. function Appender(logger) {
  552.     // add listener to the logger methods
  553.     logger.onlog.addListener(this);
  554.     /**
  555.      * set reference to calling logger
  556.      * @type Log4js.Logger
  557.      * @private
  558.      */
  559.     this.logger = logger;
  560. }
  561.  
  562. Appender.prototype = {
  563.     /** 
  564.      * appends the given loggingEvent appender specific
  565.      * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to append
  566.      */
  567.     doAppend: function(loggingEvent) {
  568.         return;
  569.     },
  570.     
  571.     /**
  572.      * Set the Layout for this appender.
  573.      * @param {Layout} layout Layout for formatting loggingEvent
  574.      */
  575.     setLayout: function(layout){
  576.         this.layout = layout;
  577.     } 
  578. };
  579.  
  580. /**
  581.  * Interface for Layouts.
  582.  * Use this Layout as "interface" for other Layouts. It is doing nothing.
  583.  *
  584.  * @constructor
  585.  * @author Stephan Strittmatter
  586.  */
  587. function Layout() {return;}
  588. Layout.prototype = {
  589.     /** 
  590.      * Implement this method to create your own layout format.
  591.      * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format
  592.      * @return formatted String
  593.      * @type String
  594.      */
  595.     format: function(loggingEvent) {
  596.         return "";
  597.     },
  598.     /** 
  599.      * Returns the content type output by this layout. 
  600.      * @return The base class returns "text/plain".
  601.      * @type String
  602.      */
  603.     getContentType: function() {
  604.         return "text/plain";
  605.     },
  606.     /** 
  607.      * @return Returns the header for the layout format. The base class returns null.
  608.      * @type String
  609.      */
  610.     getHeader: function() {
  611.         return null;
  612.     },
  613.     /** 
  614.      * @return Returns the footer for the layout format. The base class returns null.
  615.      * @type String
  616.      */
  617.     getFooter: function() {
  618.         return null;
  619.     }
  620. };
  621.  
  622. /**
  623.  * Appender writes the logs to the Shell of Firefox when it is launched with
  624.  * firefox -console (and has the necessary properties enabled)
  625.  * PLEASE NOTE - Only works in Firefox
  626.  * @constructor
  627.  * @extends Appender  
  628.  * @param logger log4js instance this appender is attached to
  629.  * @author Stephan Strittmatter
  630.  */
  631. function FirefoxConsoleAppender(logger) {
  632.     // add listener to the logger methods
  633.     logger.onlog.addListener(this);
  634.  
  635.     this.logger = logger;
  636.     this.layout = new MozStackLayout(true);
  637.  
  638. }
  639.  
  640. FirefoxConsoleAppender.superclass = Appender.prototype;
  641. FirefoxConsoleAppender.prototype = {
  642.     /** 
  643.      * @see Appender#doAppend
  644.      */
  645.     doAppend: function(loggingEvent) {
  646.         dump(this.layout.format(loggingEvent));
  647.     },
  648.     /**
  649.      * @see Appender#setLayout
  650.      */
  651.     setLayout: function(layout){
  652.         this.layout = layout;
  653.     }
  654. };
  655.  
  656. /**
  657.  * Appender writes the logs to the JavaScript console of Mozilla browser
  658.  * More infos: http://kb.mozillazine.org/index.php?title=JavaScript_Console&redirect=no
  659.  * PLEASE NOTE - Only works in Mozilla browser
  660.  * @constructor
  661.  * @extends Appender  
  662.  * @param logger log4js instance this appender is attached to
  663.  * @author Stephan Strittmatter
  664.  */
  665. function MozJSConsoleAppender(logger) {
  666.     // add listener to the logger methods
  667.     logger.onlog.addListener(this);
  668.  
  669.     this.logger = logger;
  670.     this.layout = new SimpleLayout();
  671.     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
  672.     this.jsConsole = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
  673.     this.scriptError = Components.classes["@mozilla.org/scripterror;1"].createInstance(Components.interfaces.nsIScriptError);
  674. }
  675.  
  676. MozJSConsoleAppender.superclass = Appender.prototype;
  677. MozJSConsoleAppender.prototype = {
  678.     /** 
  679.      * @see Appender#doAppend
  680.      */
  681.     doAppend: function(loggingEvent) {
  682.         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
  683.         this.scriptError.init(this.layout.format(loggingEvent), null, null, null, null, this.getFlag(loggingEvent), loggingEvent.categoryName);
  684.         this.jsConsole.logMessage(this.scriptError);
  685.     },
  686.     /**
  687.      * @see Appender#setLayout
  688.      */
  689.     setLayout: function(layout){
  690.         this.layout = layout;
  691.     },
  692.     /**
  693.      * map Log4js.Level to jsConsole Flag
  694.      * @private
  695.      */    
  696.     getFlag: function(loggingEvent)
  697.     {
  698.         var retval;
  699.         switch (loggingEvent.level) {    
  700.             case Log4js.Level.FATAL:
  701.                 retval = 2;//nsIScriptError.exceptionFlag = 2
  702.                 break;
  703.             case Log4js.Level.ERROR:
  704.                 retval = 0;//nsIScriptError.errorFlag
  705.                 break;
  706.             case Log4js.Level.WARN:
  707.                 retval = 1;//nsIScriptError.warningFlag = 1
  708.                 break;
  709.             default:
  710.                 retval = 1;//nsIScriptError.warningFlag = 1
  711.                 break;
  712.         }
  713.         //nsIScriptError.strictFlag = 4
  714.         
  715.         return retval;        
  716.     }
  717. };
  718.  
  719. /**
  720.  * Appender writes the logs to a local file
  721.  * PLEASE NOTE - Only works in Firefox
  722.  * @constructor
  723.  * @extends Appender  
  724.  * @param logger log4js instance this appender is attached to
  725.  * @author Andrew Mutton
  726.  */
  727. function FirefoxFileAppender(logger, filename) {
  728.     // add listener to the logger methods
  729.     logger.onlog.addListener(this);
  730.  
  731.     this.logger = logger;
  732.     this.filename = filename;
  733.     this.layout = new SimpleLayout();
  734. }
  735.  
  736. FirefoxFileAppender.superclass = Appender.prototype;
  737. FirefoxFileAppender.prototype = {
  738.     /** 
  739.      * @see Appender#doAppend
  740.      */
  741.     doAppend: function(loggingEvent) {
  742.         var data = this.layout.format(loggingEvent);
  743.         try {
  744.             // file is nsIFile, data is a string
  745.             var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
  746.                                      .createInstance(Components.interfaces.nsIFileOutputStream);
  747.             var data = this.layout.format(loggingEvent);
  748.             var file = Components.classes["@mozilla.org/file/local;1"]
  749.                                  .createInstance(Components.interfaces.nsILocalFile);
  750.             file.initWithPath(this.filename);
  751.             foStream.init(file, 0x02 | 0x08 | 0x10, 0664, 0);
  752.             foStream.write(data, data.length);
  753.             foStream.close();
  754.         } catch (error) {
  755.             dump(error);
  756.             dump(data);
  757.         }
  758.     },
  759.     /**
  760.      * @see Appender#setLayout
  761.      */
  762.     setLayout: function(layout){
  763.         this.layout = layout;
  764.     }
  765. };
  766.  
  767. /**
  768.  * SimpleLayout consists of the level of the log statement, followed by " - " 
  769.  * and then the log message itself. For example,
  770.  * <code>DEBUG - Hello world</code>
  771.  *
  772.  * @constructor
  773.  * @extends Layout
  774.  * @author Stephan Strittmatter
  775.  */
  776. function SimpleLayout() {
  777.     this.LINE_SEP  = "\n";
  778.     this.LINE_SEP_LEN = 1;
  779. }
  780. SimpleLayout.prototype = {
  781.     /** 
  782.      * Implement this method to create your own layout format.
  783.      * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format
  784.      * @return formatted String
  785.      * @type String
  786.      */
  787.     format: function(loggingEvent) {
  788.         return loggingEvent.level.toString() + " - " + loggingEvent.message + this.LINE_SEP;
  789.     },
  790.     /** 
  791.      * Returns the content type output by this layout. 
  792.      * @return The base class returns "text/plain".
  793.      * @type String
  794.      */
  795.     getContentType: function() {
  796.         return "text/plain";
  797.     },
  798.     /** 
  799.      * @return Returns the header for the layout format. The base class returns null.
  800.      * @type String
  801.      */
  802.     getHeader: function() {
  803.         return "";
  804.     },
  805.     /** 
  806.      * @return Returns the footer for the layout format. The base class returns null.
  807.      * @type String
  808.      */
  809.     getFooter: function() {
  810.         return "";
  811.     }
  812. };
  813.     
  814. /**
  815.  * BasicLayout is a simple layout for storing the loggs. The loggs are stored
  816.  * in following format:
  817.  * <pre>
  818.  * categoryName~startTime [logLevel] message\n
  819.  * </pre>
  820.  *
  821.  * @constructor
  822.  * @extends Layout
  823.  * @author Stephan Strittmatter
  824.  */
  825. function BasicLayout() {
  826.     this.LINE_SEP  = "\n";
  827. }
  828. BasicLayout.prototype = {
  829.     /** 
  830.      * Implement this method to create your own layout format.
  831.      * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format
  832.      * @return formatted String
  833.      * @type String
  834.      */
  835.     format: function(loggingEvent) {
  836.         return loggingEvent.categoryName + "~" + loggingEvent.startTime.toLocaleString() + " [" + loggingEvent.level.toString() + "] " + loggingEvent.message + this.LINE_SEP;
  837.     },
  838.     /** 
  839.      * Returns the content type output by this layout. 
  840.      * @return The base class returns "text/plain".
  841.      * @type String
  842.      */
  843.     getContentType: function() {
  844.         return "text/plain";
  845.     },
  846.     /** 
  847.      * @return Returns the header for the layout format. The base class returns null.
  848.      * @type String
  849.      */
  850.     getHeader: function() {
  851.         return "";
  852.     },
  853.     /** 
  854.      * @return Returns the footer for the layout format. The base class returns null.
  855.      * @type String
  856.      */
  857.     getFooter: function() {
  858.         return "";
  859.     }
  860. };
  861.  
  862. /**
  863.  * MozStackLayout is a layout that takes advantage of stack data from Mozilla. 
  864.  * <pre>
  865.  * fileName:lineNum ~ startTime [logLevel] message\n
  866.  * </pre>
  867.  *
  868.  * @constructor
  869.  * @extends Layout
  870.  * @author Stephan Strittmatter
  871.  */
  872. function MozStackLayout(showDate) {
  873.     this.LINE_SEP  = "\n";
  874.     this.showDate = showDate;
  875. }
  876. MozStackLayout.prototype = {
  877.     /** 
  878.      * Implement this method to create your own layout format.
  879.      * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format
  880.      * @return formatted String
  881.      * @type String
  882.      */
  883.     format: function(loggingEvent) {
  884.         var formatted = loggingEvent.level.toString() + " [" + loggingEvent.categoryName + "|" + loggingEvent.getStackFileName() + ":" + loggingEvent.getStackLineNum() + "] " + loggingEvent.message + this.LINE_SEP;
  885.         if (this.showDate && Log4js.simpledate) {
  886.             var d = new Log4js.simpledate.SimpleDate(loggingEvent.startTime.getTime());
  887.               formatted = d.toFormattedString("~d/~k/~y ~H:~m:~s:~S") + " " + formatted;
  888.         }
  889.         if (this.fullStack != null) {
  890.             formatted += this.fullStack + this.LINE_SEP;
  891.         }
  892.         return formatted;
  893.     },
  894.     
  895.     /** 
  896.      * Returns the content type output by this layout. 
  897.      * @return The base class returns "text/plain".
  898.      * @type String
  899.      */
  900.     getContentType: function() {
  901.         return "text/plain";
  902.     },
  903.     /** 
  904.      * @return Returns the header for the layout format. The base class returns null.
  905.      * @type String
  906.      */
  907.     getHeader: function() {
  908.         return "";
  909.     },
  910.     /** 
  911.      * @return Returns the footer for the layout format. The base class returns null.
  912.      * @type String
  913.      */
  914.     getFooter: function() {
  915.         return "";
  916.     }
  917. };
  918.  
  919. /**
  920.  * HtmlLayout write the logs in Html format.
  921.  *
  922.  * @constructor
  923.  * @extends Layout
  924.  * @author Stephan Strittmatter
  925.  */
  926. function HtmlLayout() {return;}
  927. HtmlLayout.prototype = {
  928.     /** 
  929.      * Implement this method to create your own layout format.
  930.      * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format
  931.      * @return formatted String
  932.      * @type String
  933.      */
  934.     format: function(loggingEvent) {
  935.         return "<div style=\"" + this.getStyle(loggingEvent) + "\">" +loggingEvent.level.toString() + " - " + loggingEvent.message + "</div>\n";
  936.     },
  937.     /** 
  938.      * Returns the content type output by this layout. 
  939.      * @return The base class returns "text/html".
  940.      * @type String
  941.      */
  942.     getContentType: function() {
  943.         return "text/html";
  944.     },
  945.     /** 
  946.      * @return Returns the header for the layout format. The base class returns null.
  947.      * @type String
  948.      */
  949.     getHeader: function() {
  950.         return "<html><head><title>log4js</head><body>";
  951.     },
  952.     /** 
  953.      * @return Returns the footer for the layout format. The base class returns null.
  954.      * @type String
  955.      */
  956.     getFooter: function() {
  957.         return "</body></html>";
  958.     },
  959.     
  960.     getStyle: function(loggingEvent)
  961.     {
  962.         var style;
  963.         if (loggingEvent.level.toString().search(/ERROR/) != -1) { 
  964.             style = 'color:red';
  965.         } else if (loggingEvent.level.toString().search(/FATAL/) != -1) { 
  966.             style = 'color:red';
  967.         } else if (loggingEvent.level.toString().search(/WARN/) != -1) { 
  968.             style = 'color:orange';
  969.         } else if (loggingEvent.level.toString().search(/DEBUG/) != -1) {
  970.             style = 'color:green';
  971.         } else if (loggingEvent.level.toString().search(/INFO/) != -1) {
  972.             style = 'color:white';
  973.         } else {
  974.             style = 'color:yellow';
  975.         }    
  976.         return style;
  977.     }
  978. };
  979.  
  980. /**
  981.  * XMLLayout write the logs in XML format.
  982.  * Layout is simmilar to log4j's XMLLayout:
  983.  * <pre>
  984.  * <log4js:event category="category" level="Level" client="Client" referer="ref" timestam="Date">
  985.  * <log4js:message>Logged message</log4js:message>
  986.  * </log4js:event>
  987.  * </pre>
  988.  * @constructor
  989.  * @extends Layout
  990.  * @author Stephan Strittmatter
  991.  */
  992. function XMLLayout() {return;}
  993. XMLLayout.prototype = {
  994.     /** 
  995.      * Implement this method to create your own layout format.
  996.      * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format
  997.      * @return formatted String
  998.      * @type String
  999.      */
  1000.     format: function(loggingEvent) {
  1001.         var content = "<log4js:event logger=\"";
  1002.         content += loggingEvent.categoryName + "\" level=\"";
  1003.         content += loggingEvent.level.toString() + "\" client=\"";
  1004.         content += navigator.userAgent + "\" referer=\"";
  1005.         content += location.href + "\" timestamp=\"";
  1006.         content += loggingEvent.startTime + "\">\n";
  1007.         content += "<log4js:message><![CDATA[" + loggingEvent.message + "]]></log4js:message>\n";    
  1008.          content += "</log4js:event>\n";
  1009.         
  1010.       return content;
  1011.     },
  1012.     /** 
  1013.      * Returns the content type output by this layout. 
  1014.      * @return The base class returns "text/xml".
  1015.      * @type String
  1016.      */
  1017.     getContentType: function() {
  1018.         return "text/xml";
  1019.     },
  1020.     /** 
  1021.      * @return Returns the header for the layout format. The base class returns null.
  1022.      * @type String
  1023.      */
  1024.     getHeader: function() {
  1025.         return "<log4js:eventSet version=\"" + Log4js.version + 
  1026.             "\" xmlns:log4js=\"http://log4js.berlios.de/log4js/\">\n";
  1027.     },
  1028.     /** 
  1029.      * @return Returns the footer for the layout format. The base class returns null.
  1030.      * @type String
  1031.      */
  1032.     getFooter: function() {
  1033.         return "</log4js:eventSet>\n";
  1034.     }
  1035. };
  1036.  
  1037. /**
  1038.  * JSONLayout write the logs in JSON format.
  1039.  * JSON library is required to use this Layout. See also {@link http://www.json.org}
  1040.  * @constructor
  1041.  * @extends Layout
  1042.  * @author Stephan Strittmatter
  1043.  */
  1044. function JSONLayout() {return;}
  1045. JSONLayout.prototype = {
  1046.     /** 
  1047.      * Implement this method to create your own layout format.
  1048.      * @param {Log4js.LoggingEvent} loggingEvent loggingEvent to format
  1049.      * @return formatted String
  1050.      * @type String
  1051.      */
  1052.     format: function(loggingEvent) {        
  1053.         return JSON.stringify(loggingEvent);
  1054.     },
  1055.     /** 
  1056.      * Returns the content type output by this layout. 
  1057.      * @return The base class returns "text/xml".
  1058.      * @type String
  1059.      */
  1060.     getContentType: function() {
  1061.         return "text/json";
  1062.     },
  1063.     /** 
  1064.      * @return Returns the header for the layout format. The base class returns null.
  1065.      * @type String
  1066.      */
  1067.     getHeader: function() {
  1068.         return "";
  1069.     },
  1070.     /** 
  1071.      * @return Returns the footer for the layout format. The base class returns null.
  1072.      * @type String
  1073.      */
  1074.     getFooter: function() {
  1075.         return "";
  1076.     }
  1077. };
  1078.  
  1079.  /**
  1080.   * Implementtion of java.util.HashMap
  1081.   * @private 
  1082.   */
  1083. function Map(){
  1084.     var keys = new Array();
  1085.     this.contains = function(key){
  1086.        var entry = findEntry(key);
  1087.        return !(entry == null || entry instanceof NullKey);
  1088.     }
  1089.     this.get = function(key) {
  1090.      var entry = findEntry(key);
  1091.      if ( !(entry == null || entry instanceof NullKey) )
  1092.         return entry.value;
  1093.       else
  1094.         return null;
  1095.     };
  1096.     this.put = function(key, value) {
  1097.       var entry = findEntry(key);
  1098.       if (entry){
  1099.         entry.value = value;
  1100.       } else {
  1101.         addNewEntry(key, value);
  1102.       }
  1103.     };
  1104.     this.remove = function (key){
  1105.       for (var i=0;i<keys.length;i++){
  1106.         var entry = keys[i];
  1107.         if (entry instanceof NullKey) continue;
  1108.         if (entry.key == key){
  1109.             keys[i] = NullKey;
  1110.         }
  1111.       }        
  1112.     };
  1113.     this.size = function() {
  1114.         return keys.length;
  1115.     };
  1116.     function findEntry(key){
  1117.       for (var i=0;i<keys.length;i++){
  1118.         var entry = keys[i];
  1119.         if (entry instanceof NullKey) continue;
  1120.         if (entry.key == key){
  1121.             return entry
  1122.         }
  1123.       }
  1124.       return null;
  1125.     };
  1126.     function addNewEntry(key, value){
  1127.         var entry = new Object();
  1128.         entry.key = key;
  1129.         entry.value = value;
  1130.         keys[keys.length] = entry; 
  1131.     }
  1132.   }
  1133. /**
  1134.  * replace the entries of map in key array, removing the former value
  1135.  * @private
  1136.  */
  1137. function NullKey(){
  1138. }
  1139. new NullKey();
  1140.  
  1141. /**
  1142.  * ArrayList like java.util.ArrayList
  1143.  * @private
  1144.  */
  1145. function ArrayList()
  1146. {
  1147.   this.array = new Array();
  1148. };
  1149.  
  1150. ArrayList.prototype = {
  1151.  
  1152.     add: function(obj){
  1153.         this.array[this.array.length] = obj;
  1154.     },
  1155.  
  1156.     iterator: function (){
  1157.         return new Iterator(this);
  1158.         },
  1159.   
  1160.     length: function (){
  1161.         return this.array.length;
  1162.     },
  1163.   
  1164.     get: function (index){
  1165.         return this.array[index];
  1166.     },
  1167.   
  1168.     addAll: function (obj)
  1169.     {
  1170.         if (obj instanceof Array) {
  1171.             for (var i=0;i<obj.length;i++) {
  1172.                 this.add(obj[i]);
  1173.             }
  1174.         } else if (obj instanceof ArrayList) {
  1175.             for (var j=0;j<obj.length();i++) {
  1176.                 this.add(obj.get(j));
  1177.             }
  1178.         }
  1179.     }
  1180. };
  1181.  
  1182. /**
  1183.  * Iterator for ArrayList
  1184.  * @private
  1185.  */
  1186. function Iterator (arrayList){
  1187.     this.arrayList = arrayList;
  1188.     this.index = 0;
  1189. };
  1190. Iterator.prototype = {
  1191.     hasNext: function (){
  1192.         return this.index < this.arrayList.length();
  1193.     },
  1194.     next: function() {
  1195.         return this.arrayList.get( index++ );
  1196.     }
  1197. }
  1198.